#pragma once
#ifndef EUCLIENTGUI_EUSOCKET_H
#define EUCLIENTGUI_EUSOCKET_H
#endif
#include <atlstr.h>
#include <tchar.h>
#include <Windows.h>
#include <winsock2.h>
#include "md5.h"
#ifndef EUCLIENTGUI_COMMON_H
#include "common.h"
#endif
#pragma comment(lib, "Ws2_32.lib")



typedef struct _Package_Header {
	BYTE Version;
	BYTE Flag;
	WORD PackageLen; //Network Byte Order
}Package_Header, *pPackage_Header;
typedef struct _Package_Record {
	BYTE Flag;
	BYTE RecordLen;
	BYTE Data[1];
}Package_Record, *pPackage_Record;
typedef struct _BINARY_ARRAY {
	BYTE Data[BUFSIZ];
	static const UINT TotalLen = BUFSIZ;
	UINT Len;
}BINARYARRAY, *pBINARYARRAY;

class CEuSocket
{
public:
	static CString m_HostName;
	static int m_Port;
	static CString m_UserName;
	static CString m_Password;
	static CString m_Domain;
	static LoginDomain m_LoginMethod;
	static BINARYARRAY m_EnUserName;
	static BINARYARRAY m_EnDomain;
	static BINARYARRAY m_EnPassword;
	static BINARYARRAY m_EnMAC;
	static BINARYARRAY m_EnData;
	static BINARYARRAY m_EnMode;
	static DWORD m_KeepMsg[2];
	static DWORD m_EnKey[4];
	static DWORD m_DeKey[4];
	static DWORD m_UDPKey[4];
	static CString m_LeftMoney;
	static CString m_UsedMoney;
	static LARGE_INTEGER m_DownloadBit;
	static LARGE_INTEGER m_UploadBit;
	static DWORD m_LoginTime;
	static CString m_ErrorMsg;
	static CString m_ProtocolVer;
	static DWORD m_LastTime;

	static SOCKET m_sockServer;
	static BYTE m_SendBuf[BUFSIZ];
	static BYTE m_ReceiveBuf[BUFSIZ];
	static sockaddr_in m_addrServer;		
	static HOSTENT m_RemoteHost;

public:
	CEuSocket(void);
	~CEuSocket(void);
	int InitSocket(int type);
	BOOL InitServerAddr(CString ServerName);
	int TCPSend(SOCKET sock, BYTE *TCPSendBuf, int cbDatalen);
	int TCPReceive(SOCKET sock, BYTE *TCPReceiveBuf, int cbBuflen);
	int ContructPacket(BYTE *SendBuf, int cbBuflen, BYTE HeaderFlag);
	int HandleReply(BYTE *RecieveBuf, int cbBuflen);
	int UDPSend(SOCKET sock, BYTE *UDPSendBuf, int cbDatalen);
	int UDPReceive(SOCKET sock, BYTE *UDPReceiveBuf, int cbBuflen);
	int TCPLogin(LoginDomain LoginType);
	int TCPOffline();
	int UDPLoginNet();
	int UDPQuery();
	int CryptoSendInfo(LoginDomain LoginType);
private:
	int AppendItemToPackage(BYTE *PackageStart, int TotalLen, BYTE *ItemStart, int ItemLen, BYTE Itemflag);
	int MoveItemFromPackage(BYTE *PackageStart, BYTE *ItemStart, int BufLen, BYTE &ItemFlag, int &ItemLen);
	int CharToHex(TCHAR * pStr, int StrLen, BYTE *pHex);
	int HexToChar(BYTE *pHex, int ByteLen, TCHAR *pStr);
	void Tean_Crypt(DWORD *Plaintext, DWORD *Key, DWORD *Cyphertext);
	void Tean_Decrypt(DWORD *CypherText, DWORD *Key, DWORD *PlainText);
	int Package_Crypt(BYTE *PlainBuf, int PlainLen, DWORD *Key, BYTE *CypherBuf, int CyperBufLen);
	int Package_Decrypt(BYTE *CypherBuf, int CypherLen, DWORD *Key, BYTE *PlainBuf, int PlainBufLen);
	int EuMD5(BYTE *pPackage);
	int ComputeStream(LARGE_INTEGER Stream, CString &m_NotifyMsg);
	int ComputeTime(DWORD Time, CString &m_LastTime);
};
